package com.xyy.saas.payment.adpater.wxPayHandler;

import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.WxUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author zhangwenxiong
 * @Date 2020/12/1 14:34
 * @Version 1.0
 */
public class WxPayAdapterService {
    private ConcurrentHashMap<String, Method> concurrentHashMap = new ConcurrentHashMap();

    private static WxPayAdapterService instance;

    private Class WxPayAdapterServiceClass = Class.forName("com.xyy.saas.payment.adpater.wxPayHandler.WxPayAdapterService");

    public WxPayAdapterService() throws ClassNotFoundException {
    }

    public static WxPayAdapterService getInstance(){
        if (null == instance){
            synchronized (WxPayAdapterService.class){
                if (null == instance){
                    try {
                        instance = new WxPayAdapterService();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return instance;
    }

    public void invoker(String methodName, Map<String, Object> reqMap, Map<String, Object> params) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = concurrentHashMap.get(methodName);
        if (method==null){
            method = WxPayAdapterServiceClass.getMethod(methodName, Map.class, Map.class);
            concurrentHashMap.put(methodName, method);
        }
        method.invoke(getInstance(), reqMap, params);
    }

    public String invokerResult(String methodName,Map<String, String> wxParam,Map<String, String> resultParamsMap) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = concurrentHashMap.get(methodName);
        if (method==null){
            method = WxPayAdapterServiceClass.getMethod(methodName, Map.class, Map.class);
            concurrentHashMap.put(methodName, method);
        }
        return String.valueOf(method.invoke(getInstance(), wxParam, resultParamsMap));
    }

    public void qr(Map<String, String> reqMap, Map<String, String> params){
        reqMap.put("trade_type","NATIVE");
        reqMap.put("product_id",params.get("productId"));
    }

    public void h5(Map<String, String> reqMap, Map<String, String> params){
        reqMap.put("trade_type","MWEB");
    }

    public void mini(Map<String, String> reqMap, Map<String, String> params){
        reqMap.put("trade_type","JSAPI");
        reqMap.put("openid", params.get("openId"));
    }

    public void pub(Map<String, String> reqMap, Map<String, String> params){
        reqMap.put("trade_type","JSAPI");
        reqMap.put("openid", params.get("openId"));
    }

    public void app(Map<String, String> reqMap, Map<String, String> params){
        reqMap.put("trade_type","APP");
    }

    public String qrResult(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        return resultParamsMap.get("code_url");
    }

    public String h5Result(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        return resultParamsMap.get("mweb_url");
    }

    public String appResult(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        return getSignResult(wxParam, resultParamsMap);
    }

    public String miniResult(Map<String, String> wxParam,Map<String, String> resultParamsMap){
       return getMiniSignResult(wxParam, resultParamsMap);
    }

    public String pubResult(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        return getMiniSignResult(wxParam, resultParamsMap);
    }

    public String pubResultbasic(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        return getMiniSignResultBasic(wxParam, resultParamsMap);
    }

    public String miniResultbasic(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        return getMiniSignResultBasic(wxParam, resultParamsMap);
    }

    private String getMiniSignResult(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        Map<String, Object> resultMap = new TreeMap<>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 升序排序
                        return obj1.compareTo(obj2);
                    }
                });
        resultMap.put("appId", resultParamsMap.get("appid"));
        //解析随机字符串
        resultMap.put("nonceStr", WxUtil.getNonceStr());
        resultMap.put("package", "prepay_id=" + resultParamsMap.get("prepay_id"));
        resultMap.put("signType", "MD5");
        //时间戳
        resultMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));
        String paySign = WxUtil.getSign(resultMap, wxParam.get("apiKey"));
        resultMap.put("paySign", paySign);
        return resultMap.toString();
    }

    private String getMiniSignResultBasic(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        Map<String, Object> resultMap = new TreeMap<>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 升序排序
                        return obj1.compareTo(obj2);
                    }
                });
        resultMap.put("appId", resultParamsMap.get("appid"));
        //解析随机字符串
        resultMap.put("nonceStr", WxUtil.getNonceStr());
        resultMap.put("package", "prepay_id=" + resultParamsMap.get("prepay_id"));
        resultMap.put("signType", "MD5");
        //时间戳
        resultMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));
        String paySign = WxUtil.getSign(resultMap, wxParam.get("apiKey"));
        resultMap.put("paySign", paySign);
        return JSONUtils.toJSON(resultMap);
    }

    private String getSignResult(Map<String, String> wxParam,Map<String, String> resultParamsMap){
        Map<String, Object> resultMap = new TreeMap<>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 升序排序
                        return obj1.compareTo(obj2);
                    }
                });
        Map<String, Object> signMap = new TreeMap<>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 升序排序
                        return obj1.compareTo(obj2);
                    }
                });

        resultMap.put("appId", resultParamsMap.get("appid"));
        resultMap.put("partnerId", resultParamsMap.get("mch_id"));
        //解析随机字符串
        resultMap.put("nonceStr", WxUtil.getNonceStr());
        resultMap.put("prepayId", resultParamsMap.get("prepay_id"));
        //时间戳
        resultMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));
        resultMap.put("packageValue", "Sign=WXPay");
        resultMap.put("signType", "MD5");

        signMap.put("appid", resultParamsMap.get("appid"));
        signMap.put("partnerid", resultParamsMap.get("mch_id"));
        signMap.put("prepayid", resultParamsMap.get("prepay_id"));
        signMap.put("package", "Sign=WXPay");
        signMap.put("noncestr", resultMap.get("nonceStr"));
        signMap.put("timestamp", resultMap.get("timeStamp"));
        String paySign = WxUtil.getSign(signMap, wxParam.get("apiKey"));
        resultMap.put("sign", paySign);
        return JSONUtils.toJSON(resultMap);
    }
}
